

package SSF.Net;

import java.util.*;

import org.omg.CORBA.FREE_MEM;

import SSF.Net.Util.*;
import SSF.OS.*;

import com.renesys.raceway.DML.*;
import com.renesys.raceway.SSF.*;

/** Class implementing the special case of a link layer with exactly 
  * two attached interfaces: a point-to-point link. 
  */
public class ptpLinkLayer extends Entity implements linkLayer {
  private link forLink;
  public link onLink() { return forLink; }
  NIC[] ends;

  protected inChannel in(NIC fromNIC){
    if (ends[0] == fromNIC) return ends[1].IN;
    if (ends[1] == fromNIC) return ends[0].IN;
    return null;
  };

/** Bring up the given NIC over this link layer */
  public void up(NIC nic) {
    long channelDelay = (long)(nic.delay()+onLink().delay());
    nic.OUT =  new outChannel(nic.inGraph(),channelDelay);
    if (ends[0] == nic) 
      ends[0].OUT.mapto(ends[1].IN);
    else if (ends[1] == nic) 
      ends[1].OUT.mapto(ends[0].IN);
  }


  public ptpLinkLayer(link L) {
    alignTo(forLink = L);

    try {
      Enumeration eset = forLink.attachedInterfaces.elements();
      
      ends = new NIC[2];
      ends[0] = (NIC)eset.nextElement();
      ends[1] = (NIC)eset.nextElement();
      
      Host h0 = (Host)ends[0].inGraph();
      Host h1 = (Host)ends[1].inGraph();
      
      ProtocolSession ip0 = h0.SessionForName("ip");
      ProtocolSession ip1 = h1.SessionForName("ip");
      
      ends[0].open(ip0,this);
      ends[1].open(ip1,this);
    } catch (ProtocolException pex) {
      pex.printStackTrace();
    }
  }

/** Send a packet with the given queueing delay */
  public void transmit(NIC forNIC, PacketEvent pevt, long qdelay){
	if (forLink.failFrom != null && forLink.failUntil != null)
	{
		if (now() / Net.frequency < forLink.failUntil && forLink.failFrom <= now() / Net.frequency)
		{
			return;
		}
	}
	
	
    if (forLink.dumpTo!=null) {
      synchronized(forLink.dumpTo) {
	forLink.dumpTo.dump(pevt);	
      }	
    }
    forNIC.OUT.write(pevt,qdelay);
  }

/** Poll the link layer for any packets available for receipt */
  public /*SSF.*/Event[] receive(NIC forNIC){
    return forNIC.IN.activeEvents();
  }

  public NIC peer(NIC forNIC) {
    return(ends[0] == forNIC? ends[1]:(ends[1] == forNIC? ends[0]: null));
  }
  public Enumeration peers(NIC forNIC) {
    return new ptpPeerEnumeration(peer(forNIC));
  }
  class ptpPeerEnumeration implements java.util.Enumeration {
    NIC nic;
    public ptpPeerEnumeration(NIC n) { nic = n; }
    public boolean hasMoreElements() { return (nic != null); }
    public Object nextElement() { 
      NIC rnic = nic; 
      nic = null; 
      return rnic;
    }
  }
}



/*=                                                                      =*/
/*=  Copyright (c) 1997--2000  SSF Research Network                      =*/
/*=                                                                      =*/
/*=  SSFNet is open source software, distributed under the GNU General   =*/
/*=  Public License.  See the file COPYING in the 'doc' subdirectory of  =*/
/*=  the SSFNet distribution, or http://www.fsf.org/copyleft/gpl.html    =*/
/*=                                                                      =*/
